package ext.tianma.access;

import java.io.IOException;
import java.io.Serializable;
import java.util.Enumeration;
import java.util.Locale;
import java.util.Vector;

import wt.access.AccessControlHelper;
import wt.access.AccessPermission;
import wt.access.AdHocAccessKey;
import wt.access.AdHocControlled;
import wt.access.WTAclEntry;
import wt.fc.ObjectIdentifier;
import wt.fc.ObjectReference;
import wt.fc.Persistable;
import wt.fc.PersistenceHelper;
import wt.fc.PersistenceServerHelper;
import wt.inf.container.WTContained;
import wt.inf.container.WTContainer;
import wt.inf.container.WTContainerHelper;
import wt.org.WTPrincipal;
import wt.org.WTPrincipalReference;
import wt.part.WTPart;
import wt.pom.Transaction;
import wt.session.SessionServerHelper;
import wt.team.Team;
import wt.team.TeamManaged;
import wt.team.TeamReference;
import wt.util.WTException;
import wt.util.WTProperties;
import wt.util.WTPropertyVetoException;
import wt.workflow.engine.WfActivity;
import wt.workflow.engine.WfBlock;
import wt.workflow.engine.WfConnector;
import wt.workflow.engine.WfProcess;
import wt.workflow.work.WorkItem;
//import ext.com.epm.EPMUtil;
//import ext.com.part.PartUtil;

public class AccessUtil implements Serializable {
	private static final AdHocAccessKey CUST_ACL_KEY = AdHocAccessKey
			.toAdHocAccessKey("8");
	private static boolean VERBOSE;
	static {
		try {
			WTProperties wtproperties = WTProperties.getLocalProperties();
			VERBOSE = wtproperties.getProperty("ext.com.access.verbose", false);
		} catch (IOException ioe) {
			ioe.printStackTrace();
		}
	}

	public AccessUtil() {
	}

	/**
	 * 设置对象权限
	 * 
	 * @param persistable
	 *            要设置权限的对象
	 * @param wtprincipal
	 *            要设置权限的用户/组
	 * @param accessPermission
	 *            需要设置的权限
	 * @return Persistable 设置权限后的对象
	 * @throws WTException
	 * @throws wt.util.WTPropertyVetoException
	 * 
	 * <br>
	 * <br>
	 *             <b>Revision History</b> <br>
	 *             <b>Rev:</b> 1.0 - 2006/03/30, Tracy Dou <br>
	 *             <b>Comment:</b> Initial release.
	 */
	public static Persistable setObjectAccess(Persistable persistable,
			WTPrincipal wtprincipal, AccessPermission accessPermission)
			throws WTException, wt.util.WTPropertyVetoException {
		boolean flag = SessionServerHelper.manager.setAccessEnforced(false);
		Transaction transaction = new Transaction();
		try {
			transaction.start();

			WTPrincipalReference wtprincipalreference = WTPrincipalReference
					.newWTPrincipalReference(wtprincipal);

			Vector vector = new Vector();
			vector.add(accessPermission);

			persistable = PersistenceHelper.manager.refresh(persistable);
			if (persistable instanceof AdHocControlled) {
				AdHocControlled adhoccontrolled = (AdHocControlled) persistable;
				try {
					adhoccontrolled = AccessControlHelper.manager
							.addPermissions(adhoccontrolled,
									wtprincipalreference, vector,
									AdHocAccessKey.WNC_ACCESS_CONTROL);
					PersistenceServerHelper.manager.update(adhoccontrolled,
							false);
				} catch (Exception exception) {
					if (VERBOSE)
						System.out.println(exception.getLocalizedMessage());
					System.out.println("Failed on object: " + adhoccontrolled);
				}

			}

			transaction.commit();
			transaction = null;
			Persistable persistable1 = persistable;
			return persistable1;
		} finally {
			if (transaction != null)
				transaction.rollback();
			SessionServerHelper.manager.setAccessEnforced(flag);
		}
	}

	/**
	 * 设置对象权限
	 * 
	 * @param persistable
	 *            要设置权限的对象
	 * @param wtprincipalreference
	 *            要设置权限的用户/组，为WTPrincipalReference
	 * @param permission
	 *            需要设置的权限
	 * @return Persistable 设置权限后的对象
	 * @throws WTException
	 * @throws wt.util.WTPropertyVetoException
	 * 
	 * <br>
	 * <br>
	 *             <b>Revision History</b> <br>
	 *             <b>Rev:</b> 1.0 - 2006/03/30, Tracy Dou <br>
	 *             <b>Comment:</b> Initial release.
	 */
	public static Persistable setObjectAccess(Persistable persistable,
			WTPrincipalReference wtprincipalreference,
			AccessPermission permission) throws WTException,
			wt.util.WTPropertyVetoException {
		if ((wtprincipalreference == null)
				|| !(persistable instanceof AdHocControlled)
				|| (permission == null))
			return persistable;

		WTPrincipal wtprincipal = wtprincipalreference.getPrincipal();
		persistable = setObjectAccess(persistable, wtprincipal, permission);

		return persistable;
	}

	/**
	 * 收回对象权限
	 * 
	 * @param persistable
	 *            要收回权限的对象
	 * @param wtprincipal
	 *            要收回权限的用户/组
	 * @param accessPermission
	 *            需要收回的权限
	 * @return Persistable 设置权限后的对象
	 * @throws WTException
	 * @throws wt.util.WTPropertyVetoException
	 * 
	 * <br>
	 * <br>
	 *             <b>Revision History</b> <br>
	 *             <b>Rev:</b> 1.0 - 2006/03/30, Tracy Dou <br>
	 *             <b>Comment:</b> Initial release.
	 */
	public static Persistable removeObjectAccess(Persistable persistable,
			WTPrincipal wtprincipal, AccessPermission accessPermission)
			throws WTException, wt.util.WTPropertyVetoException {
		boolean flag = SessionServerHelper.manager.setAccessEnforced(false);
		Transaction transaction = new Transaction();
		try {
			transaction.start();

			WTPrincipalReference wtprincipalreference = WTPrincipalReference
					.newWTPrincipalReference(wtprincipal);

			Vector vector = new Vector();
			vector.add(accessPermission);

			persistable = PersistenceHelper.manager.refresh(persistable);
			if (persistable instanceof AdHocControlled) {
				AdHocControlled adhoccontrolled = (AdHocControlled) persistable;
				try {
					adhoccontrolled = AccessControlHelper.manager
							.removePermission(adhoccontrolled,
									wtprincipalreference, accessPermission,
									AdHocAccessKey.WNC_ACCESS_CONTROL);
					PersistenceServerHelper.manager.update(adhoccontrolled,
							false);
				} catch (Exception exception) {
					if (VERBOSE) {
						System.out.println(exception.getLocalizedMessage());
						System.out.println("Failed on object: "
								+ adhoccontrolled);

					}
				}

			}

			transaction.commit();
			transaction = null;
			Persistable persistable1 = persistable;
			return persistable1;
		} finally {
			if (transaction != null)
				transaction.rollback();
			SessionServerHelper.manager.setAccessEnforced(flag);
		}
	}

	/**
	 * 收回对象权限
	 * 
	 * @param persistable
	 *            要收回权限的对象
	 * @param wtprincipalreference
	 *            要收回权限的用户/组，为WTPrincipalReference
	 * @param permission
	 *            需要收回的权限
	 * @return Persistable 设置权限后的对象
	 * @throws WTException
	 * @throws wt.util.WTPropertyVetoException
	 * 
	 * <br>
	 * <br>
	 *             <b>Revision History</b> <br>
	 *             <b>Rev:</b> 1.0 - 2006/03/30, Tracy Dou <br>
	 *             <b>Comment:</b> Initial release.
	 */
	public static Persistable removeObjectAccess(Persistable persistable,
			WTPrincipalReference wtprincipalreference,
			AccessPermission permission) throws WTException,
			wt.util.WTPropertyVetoException {
		if ((wtprincipalreference == null)
				|| !(persistable instanceof AdHocControlled)
				|| (permission == null))
			return persistable;

		WTPrincipal wtprincipal = wtprincipalreference.getPrincipal();
		persistable = removeObjectAccess(persistable, wtprincipal, permission);

		return persistable;
	}

	/**
	 * 显示对象权限
	 * 
	 * @param obj
	 *            要显示所设置的权限的对象
	 * @return Sting 设置的权限信息
	 * @throws WTException
	 * 
	 * <br>
	 * <br>
	 *             <b>Revision History</b> <br>
	 *             <b>Rev:</b> 1.0 - 2006/03/30, Tracy Dou <br>
	 *             <b>Comment:</b> Initial release.
	 */
	public static String showAdHocAcl(Object obj) throws WTException {
		if (!(obj instanceof AdHocControlled))
			return "";
		StringBuffer stringbuffer = new StringBuffer();
		for (Enumeration enumeration = AccessControlHelper.manager
				.getEntries((AdHocControlled) obj); enumeration
				.hasMoreElements();) {
			stringbuffer.append("\n        ");
			WTAclEntry wtaclentry = (WTAclEntry) enumeration.nextElement();
			AdHocAccessKey adhocaccesskey = wtaclentry.getOwnerKey();
			stringbuffer.append(adhocaccesskey.getDisplay());
			stringbuffer.append(" (" + wtaclentry.getOwnerId() + ") ");
			WTPrincipalReference wtprincipalreference = wtaclentry
					.getPrincipalReference();
			stringbuffer.append(" "
					+ wtprincipalreference.getName()
					+ " ("
					+ ((ObjectIdentifier) wtprincipalreference.getKey())
							.getId() + "): ");
			for (wt.util.EnumeratorVector enumeratorvector = wtaclentry
					.getPermissions(); enumeratorvector.hasMoreElements();) {
				AccessPermission accesspermission = (AccessPermission) enumeratorvector
						.nextElement();
				stringbuffer.append(accesspermission.getDisplay(Locale.US));
				if (enumeratorvector.hasMoreElements())
					stringbuffer.append(", ");
			}

		}
		return stringbuffer.toString();
	}

	/**
	 * 给部件关联文档设置权限
	 * 
	 * @param thePart
	 *            要设置权限的部件，由其进行查找关联的描述文档
	 * @param wtprincipal
	 *            要设置权限的用户/组
	 * @param permission
	 *            需要设置的权限
	 * @throws WTException
	 * @throws WTPropertyVetoException
	 * @throws Exception
	 * 
	 * <br>
	 * <br>
	 *             <b>Revision History</b> <br>
	 *             <b>Rev:</b> 1.0 - 2006/03/30, Tracy Dou <br>
	 *             <b>Comment:</b> Initial release.
	 */
	/*public static void setPartDescDocsAccess(WTPart thePart,
			WTPrincipal wtprincipal, AccessPermission permission,
			boolean discribeDoc, boolean referenceDoc) throws WTException,
			WTPropertyVetoException, Exception {
		if ((wtprincipal == null) || (thePart == null) || (permission == null))
			return;

		// 获取部件相关的普通文档
		Vector docVector = PartUtil.getRelatedDocListByPart(thePart,
				discribeDoc, referenceDoc);
		for (int i = 0; i < docVector.size(); i++) {
			Persistable doc1 = (Persistable) docVector.elementAt(i);
			setObjectAccess(doc1, wtprincipal, permission);
		}

		// 获取部件相关 CAD 文档
		Vector epmVector = EPMUtil.getAllRelatedCADListByPart(thePart);
		for (int i = 0; i < epmVector.size(); i++) {
			Persistable doc2 = (Persistable) epmVector.elementAt(i);
			setObjectAccess(doc2, wtprincipal, permission);
		}
	}*/

	/**
	 * 收回部件关联文档设置权限
	 * 
	 * @param thePart
	 *            要设置权限的部件，由其进行查找关联的描述文档
	 * @param wtprincipal
	 *            要设置权限的用户/组
	 * @param permission
	 *            需要收回的权限
	 * @throws WTException
	 * @throws WTPropertyVetoException
	 * 
	 * <br>
	 * <br>
	 *             <b>Revision History</b> <br>
	 *             <b>Rev:</b> 1.0 - 2006/03/30, Tracy Dou <br>
	 *             <b>Comment:</b> Initial release.
	 */
/*//	public static void removePartDescDocsAccess(WTPart thePart,
//			WTPrincipal wtprincipal, AccessPermission permission,
//			boolean discribeDoc, boolean referenceDoc) throws WTException,
//			WTPropertyVetoException {
//		if ((wtprincipal == null) || (thePart == null) || (permission == null))
//			return;
//
//		// 获取部件相关的普通文档
//		Vector docVector = PartUtil.getRelatedDocListByPart(thePart,
//				discribeDoc, referenceDoc);
//		for (int i = 0; i < docVector.size(); i++) {
//			Persistable doc1 = (Persistable) docVector.elementAt(i);
//			removeObjectAccess(doc1, wtprincipal, permission);
//		}
//
//		// 获取部件相关 CAD 文档
//		Vector epmVector = EPMUtil.getAllRelatedCADListByPart(thePart);
//		for (int i = 0; i < epmVector.size(); i++) {
//			Persistable doc2 = (Persistable) epmVector.elementAt(i);
//			removeObjectAccess(doc2, wtprincipal, permission);
//		}
//
//	}
*/
	/**
	 * 给部件关联文档设置权限
	 * 
	 * @param thePart
	 *            要设置权限的部件，由其进行查找关联的描述文档和参考文档
	 * @param wtprincipalreference
	 *            要设置权限的用户/组,WTPrincipalReference
	 * @param permission
	 *            需要设置的权限
	 * @param discribeDoc
	 *            是否包括描述文档
	 * @param referenceDoc
	 *            是否包括参考文档
	 * @throws WTException
	 * @throws WTPropertyVetoException
	 * @throws Exception
	 * 
	 * <br>
	 * <br>
	 *             <b>Revision History</b> <br>
	 *             <b>Rev:</b> 1.0 - 2006/03/30, Tracy Dou <br>
	 *             <b>Comment:</b> Initial release.
	 */
/*	public static void setPartDescDocsAccess(WTPart thePart,
			WTPrincipalReference wtprincipalreference,
			AccessPermission permission, boolean discribeDoc,
			boolean referenceDoc) throws WTException, WTPropertyVetoException,
			Exception {
		if ((wtprincipalreference == null) || (thePart == null)
				|| (permission == null))
			return;

		WTPrincipal wtprincipal = wtprincipalreference.getPrincipal();
		setPartDescDocsAccess(thePart, wtprincipal, permission, discribeDoc,
				referenceDoc);
	}*/

	/**
	 * 收回部件关联文档设置权限
	 * 
	 * @param thePart
	 *            要设置权限的部件，由其进行查找关联的描述文档
	 * @param wtprincipalreference
	 *            要设置权限的用户/组,WTPrincipalReference
	 * @param permission
	 *            需要收回的权限
	 * @param discribeDoc
	 *            是否包括描述文档
	 * @param referenceDoc
	 *            是否包括参考文档
	 * @throws WTException
	 * @throws WTPropertyVetoException
	 * 
	 * <br>
	 * <br>
	 *             <b>Revision History</b> <br>
	 *             <b>Rev:</b> 1.0 - 2006/03/30, Tracy Dou <br>
	 *             <b>Comment:</b> Initial release.
	 */
/*	public static void removePartDescDocsAccess(WTPart thePart,
			WTPrincipalReference wtprincipalreference,
			AccessPermission permission, boolean discribeDoc,
			boolean referenceDoc) throws WTException, WTPropertyVetoException {
		if ((wtprincipalreference == null) || (thePart == null)
				|| (permission == null))
			return;

		WTPrincipal wtprincipal = wtprincipalreference.getPrincipal();
		removePartDescDocsAccess(thePart, wtprincipal, permission, discribeDoc,
				referenceDoc);
	}*/

	/**
	 * 流程中设置特定角色的参与者对pbo的某一指定权限（读取，修改等）
	 * 
	 * @param processObj
	 *            流程本身
	 * @param roleName
	 *            特定角色
	 * @param pbo
	 *            流程PBO
	 * @param ap
	 *            动态权限，如读取、修改等
	 * @throws Exception
	 * 
	 * <br>
	 * <br>
	 *             <b>Revision History</b> <br>
	 *             <b>Rev:</b> 1.0 - 2006/03/08, Tracy Dou <br>
	 *             <b>Comment:</b> Initial release.
	 */
	public static void setAclForRole(Object processObj, String roleName,
			Object pbo, AccessPermission ap) throws Exception {
		if (processObj == null || roleName == null || roleName.length() == 0
				|| pbo == null || ap == null)
			return;

		WfProcess wfprocess = getProcess(processObj);

		// 获取流程 团队的特定角色的参与者
		Team team = (Team) ((TeamReference) ((TeamManaged) wfprocess)
				.getTeamId()).getObject();
		team = (Team) PersistenceHelper.manager.refresh(team);

		wt.project.Role role = (wt.project.Role) (wt.project.Role
				.toRole(roleName));

		Enumeration participants = team.getPrincipalTarget(role);
		;
		if ((participants == null) || (!participants.hasMoreElements()))
			return;

		// 对参与者给予权限
		while (participants.hasMoreElements()) {
			WTPrincipalReference principalRef = (WTPrincipalReference) participants
					.nextElement();
			WTContainer container = WTContainerHelper
					.getContainer((WTContained) pbo);
			setObjectAccess((Persistable) pbo, principalRef.getPrincipal(), ap);
		}
	}

	/**
	 * 流程中取消特定角色的参与者对pbo的某一指定权限（读取，修改等）
	 * 
	 * @param processObj
	 *            流程本身
	 * @param roleName
	 *            特定角色
	 * @param pbo
	 *            流程PBO
	 * @param ap
	 *            动态权限，如读取、修改等
	 * @throws Exception
	 * 
	 * <br>
	 * <br>
	 *             <b>Revision History</b> <br>
	 *             <b>Rev:</b> 1.0 - 2006/03/08, Tracy Dou <br>
	 *             <b>Comment:</b> Initial release.
	 */
	public static void removeAclForRole(Object processObj, String roleName,
			Object pbo, AccessPermission ap) throws Exception {
		if (processObj == null || roleName == null || roleName.length() == 0
				|| pbo == null || ap == null)
			return;

		WfProcess wfprocess = getProcess(processObj);

		// 获取流程 团队的特定角色的参与者
		Team team = (Team) ((TeamReference) ((TeamManaged) wfprocess)
				.getTeamId()).getObject();
		team = (Team) PersistenceHelper.manager.refresh(team);

		wt.project.Role role = (wt.project.Role) (wt.project.Role
				.toRole(roleName));

		Enumeration participants = team.getPrincipalTarget(role);
		;
		if ((participants == null) || (!participants.hasMoreElements()))
			return;

		// 取消参与者权限
		while (participants.hasMoreElements()) {
			WTPrincipalReference principalRef = (WTPrincipalReference) participants
					.nextElement();
			WTContainer container = WTContainerHelper
					.getContainer((WTContained) pbo);
			removeObjectAccess((Persistable) pbo, principalRef.getPrincipal(),
					ap);
		}
	}

	/**
	 * Get object related workflow process
	 * 
	 * @param obj
	 *            the object associated to workflow process but not PBO
	 * @return workflow process
	 * 
	 * <br>
	 * <br>
	 *         <b>Revision History</b> <br>
	 *         <b>Rev:</b> 1.0 - 2006/03/30, Tracy Dou <br>
	 *         <b>Comment:</b> Initial release.
	 */
	public static WfProcess getProcess(Object obj) {
		if (obj == null)
			return null;

		try {
			Persistable persistable = null;

			if (obj instanceof ObjectIdentifier)
				persistable = PersistenceHelper.manager
						.refresh((ObjectIdentifier) obj);
			else if (obj instanceof ObjectReference)
				persistable = ((ObjectReference) obj).getObject();

			if (obj instanceof Persistable)
				persistable = (Persistable) obj;

			if (persistable instanceof WorkItem)
				persistable = ((WorkItem) persistable).getSource().getObject();

			if (persistable instanceof WfActivity)
				persistable = ((WfActivity) persistable).getParentProcess();

			if (persistable instanceof WfConnector)
				persistable = ((WfConnector) persistable).getParentProcessRef()
						.getObject();

			if (persistable instanceof WfBlock)
				persistable = ((WfBlock) persistable).getParentProcess();

			if (persistable instanceof WfProcess)
				return (WfProcess) persistable;
			else
				return null;
		} catch (Exception e) {
			e.printStackTrace();
		}

		return null;
	}
}